﻿// Decompiled with JetBrains decompiler
// Type: MCM.Implementation.PerCampaign.PerCampaignSettingsContainer
// Assembly: MCMv5, Version=5.10.2.0, Culture=neutral, PublicKeyToken=null
// MVID: 7AB326B9-B2B4-41C2-9177-68E944071101
// Assembly location: D:\steam\steamapps\workshop\content\261550\2859238197\bin\Win64_Shipping_Client\MCMv5.dll

using BUTR.DependencyInjection;
using BUTR.DependencyInjection.Logger;
using HarmonyLib.BUTR.Extensions;
using MCM.Abstractions;
using MCM.Abstractions.Base;
using MCM.Abstractions.Base.PerCampaign;
using MCM.Abstractions.GameFeatures;
using MCM.Abstractions.PerCampaign;
using MCM.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

#nullable enable
namespace MCM.Implementation.PerCampaign
{
  internal sealed class PerCampaignSettingsContainer : 
    BaseSettingsContainer<PerCampaignSettings>,
    IPerCampaignSettingsContainer,
    ISettingsContainer,
    ISettingsContainerHasSettingsDefinitions,
    ISettingsContainerCanOverride,
    ISettingsContainerCanReset,
    ISettingsContainerPresets,
    ISettingsContainerHasUnavailable,
    ISettingsContainerHasSettingsPack,
    ISettingsContainerCanInvalidateCache
  {
    private readonly IBUTRLogger _logger;
    private readonly IGameEventListener _gameEventListener;
    private bool _hasGameStarted;

    public event Action? InstanceCacheInvalidated;

    protected override GameDirectory RootFolder { get; }

    public PerCampaignSettingsContainer(
      IBUTRLogger<PerCampaignSettingsContainer> logger,
      IGameEventListener gameEventListener)
    {
      this._logger = (IBUTRLogger) logger;
      this._gameEventListener = gameEventListener;
      this._gameEventListener.GameStarted += new Action(this.GameStarted);
      this._gameEventListener.GameLoaded += new Action(this.GameLoaded);
      this._gameEventListener.GameEnded += new Action(this.GameEnded);
      this.RootFolder = GenericServiceProvider.GetService<IFileSystemProvider>().GetDirectory(base.RootFolder, "PerCampaign");
    }

    protected override void RegisterSettings(PerCampaignSettings? settings)
    {
      if (settings == null || GenericServiceProvider.GameScopeServiceProvider == null)
        return;
      ICampaignIdProvider service1 = GenericServiceProvider.GetService<ICampaignIdProvider>();
      string currentCampaignId;
      int num;
      if (service1 != null)
      {
        currentCampaignId = service1.GetCurrentCampaignId();
        num = currentCampaignId == null ? 1 : 0;
      }
      else
        num = 1;
      if (num != 0)
        return;
      IFileSystemProvider service2 = GenericServiceProvider.GetService<IFileSystemProvider>();
      if (service2 == null)
        return;
      this.LoadedSettings.Add(settings.Id, settings);
      GameDirectory directory1 = service2.GetOrCreateDirectory(this.RootFolder, currentCampaignId);
      GameDirectory directory2 = service2.GetOrCreateDirectory(directory1, settings.FolderName);
      GameDirectory directory3 = string.IsNullOrEmpty(settings.SubFolder) ? directory2 : service2.GetOrCreateDirectory(directory2, settings.SubFolder);
      ((IEnumerable<ISettingsFormat>) ((object) GenericServiceProvider.GetService<IEnumerable<ISettingsFormat>>() ?? (object) Array.Empty<ISettingsFormat>())).FirstOrDefault<ISettingsFormat>((Func<ISettingsFormat, bool>) (x => x.FormatTypes.Any<string>((Func<string, bool>) (y => y == settings.FormatType))))?.Load((BaseSettings) settings, directory3, settings.Id);
      settings.OnPropertyChanged("LOADING_COMPLETE");
    }

    public override bool SaveSettings(BaseSettings settings)
    {
      PerCampaignSettings perCampaignSettings = settings as PerCampaignSettings;
      if (perCampaignSettings == null || GenericServiceProvider.GameScopeServiceProvider == null)
        return false;
      ICampaignIdProvider service1 = GenericServiceProvider.GetService<ICampaignIdProvider>();
      string currentCampaignId;
      int num;
      if (service1 != null)
      {
        currentCampaignId = service1.GetCurrentCampaignId();
        num = currentCampaignId == null ? 1 : 0;
      }
      else
        num = 1;
      if (num != 0)
        return false;
      IFileSystemProvider service2 = GenericServiceProvider.GetService<IFileSystemProvider>();
      if (service2 == null)
        return false;
      GameDirectory directory1 = service2.GetOrCreateDirectory(this.RootFolder, currentCampaignId);
      GameDirectory directory2 = service2.GetOrCreateDirectory(directory1, settings.FolderName);
      GameDirectory directory3 = string.IsNullOrEmpty(settings.SubFolder) ? directory2 : service2.GetOrCreateDirectory(directory2, settings.SubFolder);
      ((IEnumerable<ISettingsFormat>) ((object) GenericServiceProvider.GetService<IEnumerable<ISettingsFormat>>() ?? (object) Array.Empty<ISettingsFormat>())).FirstOrDefault<ISettingsFormat>((Func<ISettingsFormat, bool>) (x => x.FormatTypes.Any<string>((Func<string, bool>) (y => y == perCampaignSettings.FormatType))))?.Save((BaseSettings) perCampaignSettings, directory3, perCampaignSettings.Id);
      settings.OnPropertyChanged("SAVE_TRIGGERED");
      return true;
    }

    private void GameStarted()
    {
      this._hasGameStarted = true;
      Action cacheInvalidated = this.InstanceCacheInvalidated;
      if (cacheInvalidated != null)
        cacheInvalidated();
      this.LoadedSettings.Clear();
    }

    private void GameLoaded() => this.LoadSettings();

    private IEnumerable<PerCampaignSettings> GetPerCampaignSettings()
    {
      foreach (Assembly assembly in AccessTools2.AllAssemblies().Where<Assembly>((Func<Assembly, bool>) (a => !a.IsDynamic)))
      {
        IEnumerable<PerCampaignSettings> settings;
        try
        {
          settings = (IEnumerable<PerCampaignSettings>) ((IEnumerable<Type>) AccessTools2.GetTypesFromAssemblyIfValid(assembly)).Where<Type>((Func<Type, bool>) (t => t.IsClass && !t.IsAbstract)).Where<Type>((Func<Type, bool>) (t => (object) t.GetConstructor(Type.EmptyTypes) != null)).Where<Type>((Func<Type, bool>) (t => typeof (PerCampaignSettings).IsAssignableFrom(t))).Where<Type>((Func<Type, bool>) (t => !typeof (EmptyPerCampaignSettings).IsAssignableFrom(t))).Where<Type>((Func<Type, bool>) (t => !typeof (IWrapper).IsAssignableFrom(t))).Select<Type, PerCampaignSettings>((Func<Type, PerCampaignSettings>) (t =>
          {
            try
            {
              return Activator.CreateInstance(t) as PerCampaignSettings;
            }
            catch (Exception ex1)
            {
              try
              {
                this._logger.LogError(ex1, string.Format("Failed to initialize type {0}", (object) t));
              }
              catch (Exception ex2)
              {
                this._logger.LogError(ex1, "Failed to initialize and log type!");
              }
              return (PerCampaignSettings) null;
            }
          })).OfType<PerCampaignSettings>().ToList<PerCampaignSettings>();
        }
        catch (TypeLoadException ex)
        {
          settings = (IEnumerable<PerCampaignSettings>) Array.Empty<PerCampaignSettings>();
          this._logger.LogError((Exception) ex, string.Format("Error while handling assembly {0}!", (object) assembly));
        }
        foreach (PerCampaignSettings setting in settings)
          yield return setting;
        settings = (IEnumerable<PerCampaignSettings>) null;
      }
    }

    private void LoadSettings()
    {
      foreach (PerCampaignSettings perCampaignSetting in this.GetPerCampaignSettings())
        this.RegisterSettings(perCampaignSetting);
    }

    public IEnumerable<UnavailableSetting> GetUnavailableSettings()
    {
      return this._hasGameStarted ? (IEnumerable<UnavailableSetting>) Array.Empty<UnavailableSetting>() : this.GetPerCampaignSettings().Select<PerCampaignSettings, UnavailableSetting>((Func<PerCampaignSettings, UnavailableSetting>) (setting => new UnavailableSetting(setting.Id, setting.DisplayName, UnavailableSettingType.PerCampaign)));
    }

    private void GameEnded()
    {
      this._hasGameStarted = false;
      Action cacheInvalidated = this.InstanceCacheInvalidated;
      if (cacheInvalidated != null)
        cacheInvalidated();
      this.LoadedSettings.Clear();
    }
  }
}
